package com.xiaoshuidi.cloud.module.rooms.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.framework.common.util.json.JsonUtils;
import com.xiaoshuidi.cloud.module.contract.api.ContractApi;
import com.xiaoshuidi.cloud.module.contract.vo.RoomContractApiRespVO;
import com.xiaoshuidi.cloud.module.rooms.api.roomstate.dto.RoomContractInfoDTO;
import com.xiaoshuidi.cloud.module.rooms.api.roomstate.dto.RoomTenantsInfoDTO;
import com.xiaoshuidi.cloud.module.rooms.api.roomstate.dto.UpdateRoomStateReqDTO;
import com.xiaoshuidi.cloud.module.rooms.api.roomstate.vo.GetCurrentRecordRespVO;
import com.xiaoshuidi.cloud.module.rooms.api.roomstate.vo.UpdateRoomTenantReqVO;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.roomel.vo.RoomelUpdateReqVO;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.roomel.vo.UpdateRoomelEntiry;
import com.xiaoshuidi.cloud.module.rooms.enums.RentStatusEnum;
import com.xiaoshuidi.cloud.module.rooms.enums.RoomContractStatusEnum;
import com.xiaoshuidi.cloud.module.rooms.mapper.RoomStateRecordMapper;
import com.xiaoshuidi.cloud.module.rooms.mq.producer.RoomEsProducer;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomHouse;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomStateRecord;
import com.xiaoshuidi.cloud.module.rooms.repository.RoomHouseRepository;
import com.xiaoshuidi.cloud.module.rooms.repository.RoomStateRecordRepository;
import com.xiaoshuidi.cloud.module.rooms.repository.elsticsearch.RoomelEntityRepository;
import com.xiaoshuidi.cloud.module.rooms.service.RoomStateRecordService;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * <p>
 * 房态记录 服务实现类
 * </p>
 *
 * @author hans.zhang
 * @since 2023-05-15
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RoomStateRecordServiceImpl extends ServiceImpl<RoomStateRecordMapper, RoomStateRecord> implements RoomStateRecordService {

    private final RoomStateRecordRepository roomStateRecordRepository;
    private final RoomHouseRepository roomHouseRepository;
    private final RoomEsProducer roomEsProducer;
    private final ContractApi contractApi;
    private final RoomelEntityRepository roomelEntityRepository;

    /**
     * 保存房态
     *
     * @param roomHouseId 房源地
     * @param state       房态
     * @return 房态id
     */
    @Override
    public CommonResult<Long> saveRecord(@NonNull Long roomHouseId, @NonNull String state, String beforeState) {

        RoomStateRecord po = new RoomStateRecord();
        po.setRoomId(roomHouseId);
        po.setState(state);
        po.setIsCurrentState(true);
        // 如果存在上一次房态，则记录上一次的房态是什么
        po.setBeforeState(beforeState);
        this.save(po);
        return CommonResult.success(po.getId());
    }

    @Override
    public CommonResult<Long> saveRecord(@NonNull Long roomHouseId, @NonNull String state) {
        // 查询是否有房态存在，有的话将原房态设置为非当前房态，添加新的房态，没有的话，直接插入新房态
        RoomStateRecord roomStateRecord = this.getByRoomIdAndIsCurrentState(roomHouseId);
        if (ObjectUtil.isNotEmpty(roomStateRecord)) {
            roomStateRecord.setIsCurrentState(false);
            roomStateRecordRepository.updateById(roomStateRecord);
        }
        RoomStateRecord po = new RoomStateRecord();
        po.setRoomId(roomHouseId);
        po.setState(state);
        po.setIsCurrentState(true);
        // 如果存在上一次房态，则记录上一次的房态是什么
        po.setBeforeState(ObjectUtil.isNotEmpty(roomStateRecord) ? roomStateRecord.getState() : null);
        this.save(po);
        return CommonResult.success(po.getId());
    }

    @Override
    public CommonResult<GetCurrentRecordRespVO> getCurrentRecord(Long roomHouseId) {
        RoomHouse roomHouse = roomHouseRepository.myGetById(roomHouseId);
        // 查询是否有房态存在，有的话将原房态设置为非当前房态，添加新的房态，没有的话，直接插入新房态
        RoomStateRecord roomStateRecord = getByRoomIdAndIsCurrentState(roomHouseId);
        GetCurrentRecordRespVO respVO = new GetCurrentRecordRespVO();
        if (ObjectUtil.isNotEmpty(roomStateRecord)) {
            respVO.setRoomHouseId(roomHouseId);
            respVO.setState(roomStateRecord.getState());
            respVO.setStateName(RentStatusEnum.getName(roomStateRecord.getState()));
            respVO.setIsLock(roomHouse.getIsLock());
        }
        return CommonResult.success(respVO);
    }

    @Override
    public RoomStateRecord getByRoomIdAndIsCurrentState(Long roomId) {
        List<RoomStateRecord> roomStateRecords = roomStateRecordRepository.listByRoomIdAndIsCurrentState(roomId);
        // 如果没有房态, 则插入一条新房态记录
        if(ObjectUtil.isEmpty(roomStateRecords)){
            RoomHouse roomHouse = roomHouseRepository.myGetById(roomId);
            RoomStateRecord roomStateRecord = new RoomStateRecord();
            roomStateRecord.setRoomId(roomId);
            roomStateRecord.setIsCurrentState(true);
            roomStateRecord.setState(RentStatusEnum.EMPTY.getValue());
            roomStateRecord.setTenantId(roomHouse.getTenantId());
            roomStateRecordRepository.save(roomStateRecord);
            return roomStateRecord;
        }
        if (roomStateRecords.size() == 1) {
            return roomStateRecords.get(0);
        }
        //可能存在入住中、 已预定状态
        RoomStateRecord syayingin = roomStateRecords.stream().filter(s -> RentStatusEnum.STAYINGIN.getValue().equals(s.getState())).findFirst().orElse(null);
        if (syayingin != null) {
            return syayingin;
        }
        return roomStateRecords.get(0);
    }

    /**
     * 根据合同状态修改房态
     *
     * @param updateRoomStateReqDTOS
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Boolean> updateRoomStateByContract(UpdateRoomStateReqDTO updateRoomStateReqDTOS) {
        RoomContractStatusEnum roomContractStatusEnum = updateRoomStateReqDTOS.getRoomContractStatusEnum();
        Long roomHouseId = updateRoomStateReqDTOS.getRoomHouseId();
        RoomTenantsInfoDTO roomTenantsInfo = updateRoomStateReqDTOS.getRoomTenantsInfo();
        // 查当前合同
        RoomContractApiRespVO roomContractApiRespVO = contractApi.getContractByRoomId(roomHouseId).getCheckedData();
        log.info("根据合同状态修改房态,房源:{}, 当前合同:{}", updateRoomStateReqDTOS.getRoomHouseId(), roomContractApiRespVO);
        RoomContractApiRespVO renewalContract = new RoomContractApiRespVO();
        if(ObjectUtil.isNotEmpty(roomContractApiRespVO)){
            log.info("根据合同状态修改房态,房源:{}, 查询续租合同请求参数:{}", updateRoomStateReqDTOS.getRoomHouseId(), roomContractApiRespVO.getId());
            renewalContract = contractApi.getRenewalContractByContractId(roomContractApiRespVO.getId()).getCheckedData();
            log.info("根据合同状态修改房态,房源:{}, 续租合同:{}", updateRoomStateReqDTOS.getRoomHouseId(), renewalContract);
        }

        RoomHouse roomHouse = roomHouseRepository.myGetById(roomHouseId);
            switch (roomContractStatusEnum) {
                // 待审批.待签约 -- 前置房态 + 锁定
                case PENDING:
                case NO_SIGNED:
                    roomHouse.setIsLock(true);
                    roomHouseRepository.updateById(roomHouse);
                    // 更新房态到ES
                    RoomelUpdateReqVO vo1 = new RoomelUpdateReqVO();
                    vo1.setId(roomHouseId);
                    vo1.setIsLock(true);
                    roomEsProducer.updateRoomEl(vo1);
                    break;
                // 已生效 -- 待入住 + 非锁定
                case ACTIVE:
                    saveRecord(roomHouseId, RentStatusEnum.CHECKEDIN.getValue());
                    roomHouse.setIsLock(false);
                    roomHouseRepository.updateById(roomHouse);
                    // 更新房态到ES
                    RoomelUpdateReqVO vo2 = new RoomelUpdateReqVO();
                    vo2.setId(roomHouseId);
                    vo2.setIsLock(false);
                    vo2.setHouseState(RentStatusEnum.CHECKEDIN.getValue());
                    roomEsProducer.updateRoomEl(vo2);
                    break;
                // 入住 -- 入住中
                case CHECK_IN:
                    saveRecord(roomHouseId, RentStatusEnum.STAYINGIN.getValue());
                    // 更新房态到ES
                    RoomelUpdateReqVO vo3 = new RoomelUpdateReqVO();
                    vo3.setId(roomHouseId);
                    vo3.setHouseState(RentStatusEnum.STAYINGIN.getValue());
                    vo3.setTenantinfo(ObjectUtil.isNotEmpty(roomTenantsInfo) ? JsonUtils.toJsonString(roomTenantsInfo) : "");
                    RoomContractInfoDTO roomContractInfoDTO = new RoomContractInfoDTO();
                    roomContractInfoDTO.setContractId(roomContractApiRespVO.getId());
                    roomContractInfoDTO.setExpiryDate(roomContractApiRespVO.getEndTime());
                    roomContractInfoDTO.setLeaseRenewalExpiryDate(renewalContract.getEndTime());
                    roomContractInfoDTO.setLeaseRenewalContractId(renewalContract.getId());
                    vo3.setContractInfo(ObjectUtil.isNotEmpty(roomContractInfoDTO) ? JsonUtils.toJsonString(roomContractInfoDTO) : "");
                    roomEsProducer.updateRoomEl(vo3);
                    break;
                // 正常结束,非正常结束-- 空置 + 非锁定
                case NORMAL_END:
                case ABNORMAL_END:
                    roomHouse.setIsLock(false);
                    roomHouse.setIsClean(false);
                    roomHouseRepository.updateById(roomHouse);
                    UpdateRoomelEntiry updateRoomelEntiry = new UpdateRoomelEntiry();
                    List<RoomStateRecord> roomStateRecords = roomStateRecordRepository.listByRoomIdAndIsCurrentState(roomHouseId);
                    roomStateRecords.forEach(s -> {
                        if (s.getState().equals(RentStatusEnum.STAYINGIN.getValue())) {
                            s.setIsCurrentState(false);
                            roomStateRecordRepository.updateById(s);
                            // todo 只有已预定，所以可以直接赋值 20230627。
                            updateRoomelEntiry.setHouseState(RentStatusEnum.SCHEDULED.getValue());
                        } else if (RentStatusEnum.CHECKEDIN.getValue().equals(s.getState())) {
                            s.setIsCurrentState(false);
                            roomStateRecordRepository.updateById(s);
                        }
                    });
                    if (roomStateRecords.size() == 1) {
                        saveRecord(roomHouseId, RentStatusEnum.EMPTY.getValue(), RentStatusEnum.STAYINGIN.getValue());
                        updateRoomelEntiry.setHouseState(RentStatusEnum.EMPTY.getValue());
                    }
                    // 更新房态到ES
                    updateRoomelEntiry.setId(roomHouseId);
                    updateRoomelEntiry.setIsLock(false);
                    updateRoomelEntiry.setTenantinfo(null);
                    updateRoomelEntiry.setContractInfo(null);
                    updateRoomelEntiry.setIsClean(false);
                    log.info("正常结束,非正常结束--{}", JsonUtils.toJsonString(updateRoomelEntiry));
                    roomelEntityRepository.updateRoomelEntiry(updateRoomelEntiry);
                    break;
                // 审批驳回
                case REJECT:
                    break;
                // 合同作废 , 已失效 -- 前置房态 + 非锁定
                case LOST_EFFECTIVENESS:
                case NULLIFY:
                    roomHouse.setIsLock(false);
                    roomHouseRepository.updateById(roomHouse);
                    // 更新房态到ES
                    RoomelUpdateReqVO vo5 = new RoomelUpdateReqVO();
                    vo5.setId(roomHouseId);
                    vo5.setIsLock(false);
                    roomEsProducer.updateRoomEl(vo5);
                    break;
                // 已签约待入住失效 空房 + 非锁定
                case TO_BE_CHECK_IN_LOST_EFFECTIVENESS:
                    roomHouse.setIsLock(false);
                    roomHouseRepository.updateById(roomHouse);
                    // 更新房态到数据库
                    UpdateRoomelEntiry updateRoomelEntiry2 = new UpdateRoomelEntiry();
                    saveRecord(roomHouseId, RentStatusEnum.EMPTY.getValue());
                    updateRoomelEntiry2.setHouseState(RentStatusEnum.EMPTY.getValue());
                    // 更新房态到ES
                    updateRoomelEntiry2.setId(roomHouseId);
                    updateRoomelEntiry2.setIsLock(false);
                    updateRoomelEntiry2.setTenantinfo(null);
                    updateRoomelEntiry2.setContractInfo(null);
                    roomelEntityRepository.updateRoomelEntiry(updateRoomelEntiry2);
                    break;
                //逾期
                case OVERDUE:
                    saveRecord(roomHouseId, RentStatusEnum.OVERDUE.getValue());
                    RoomelUpdateReqVO roomelUpdateReqVO = new RoomelUpdateReqVO();
                    roomelUpdateReqVO.setId(roomHouseId);
                    roomelUpdateReqVO.setHouseState(RentStatusEnum.OVERDUE.getValue());
                    roomEsProducer.updateRoomEl(roomelUpdateReqVO);
            }

        return CommonResult.success(Boolean.TRUE);
    }

    /**
     * 批量根据合同状态修改房态
     *
     * @return
     */
    @Override
    public CommonResult<Boolean> updateRoomStateByContract(List<UpdateRoomStateReqDTO> updateRoomStateReqDTOS) {
        for (UpdateRoomStateReqDTO updateRoomStateReqDTO : updateRoomStateReqDTOS) {
            this.updateRoomStateByContract(updateRoomStateReqDTO);
        }
        return CommonResult.success(Boolean.TRUE);
    }

    /**
     * 修改租住人/同住人信息
     * @param updateRoomTenantReqVO
     * @return
     */
    @Override
    public CommonResult<Boolean> updateRoomTenant(UpdateRoomTenantReqVO updateRoomTenantReqVO) {
        // 更新房源租客信息到ES
        RoomelUpdateReqVO vo2 = new RoomelUpdateReqVO();
        vo2.setId(updateRoomTenantReqVO.getRoomId());
        vo2.setTenantinfo(JsonUtils.toJsonString(updateRoomTenantReqVO.getRoomTenantsInfo()));
        roomEsProducer.updateRoomEl(vo2);
        return CommonResult.success(Boolean.TRUE);
    }
}
